package com.nineclock.system.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.sms.AliyunSmsUtils;
import com.nineclock.common.utils.PhoneNumCheckUtils;
import com.nineclock.system.service.SmsService;
import com.nineclock.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private AliyunSmsUtils smsUtils;

    @Autowired
    private SysUserService userService;

    /**
     * 发送验证码
     *
     * @param mobile
     * @param type
     */
    @Override
    public void sendSms(String mobile, String type) {
        //1. 参数合法性校验
        //判定是否为空
        if (StrUtil.isEmpty(mobile) || StrUtil.isEmpty(type)) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //判定手机号规则
        if (!PhoneNumCheckUtils.isPhoneLegal(mobile)) {
            throw new NcException(ResponseEnum.INVALID_PHONE_NUMBER);
        }
        //如果是注册, 判断手机是否已经存在 , 如果存在, 则不允许注册;
        if (type.equals("2")) { //type=2 是注册

            Boolean exists = userService.checkExists(mobile);
            if (exists) {
                throw new NcException(ResponseEnum.USER_MOBILE_EXISTS);
            }

        } else {
            //其他情况(登陆/更换管理员/重置密码) 手机号必须存在
            Boolean exists = userService.checkExists(mobile);
            if (!exists) { //手机号不存在
                throw new NcException(ResponseEnum.USER_NOT_REGISTER);
            }
        }

        //2. 生成随机数验证码
        String code = RandomUtil.randomNumbers(6);

        //3. 调用工具类发送短信验证码
        //Boolean result = smsUtils.sendSMS(mobile, code);
        Boolean result = true; //测试,直接看控制台打印
        if (!result) {
            throw new NcException(ResponseEnum.SEND_MESSAGE_ERROR);
        }

        //4. 存储验证码到redis中
        //组装redis的key
        String key = getPrefix(type) + mobile;

        //存入redis
        redisTemplate.boundValueOps(key).set(code, 5, TimeUnit.MINUTES);

        log.info("成功发送验证码, 手机号:" + mobile + ",验证码: " + code);

    }

    /**
     * 获取 验证码存储 key的前缀
     *
     * @param type
     * @return
     */
    private String getPrefix(String type) {
        String prefix = "";
        switch (type) {
            case "1":
                prefix = SMSConstant.SMS_LOGIN_KEY_PREFIX;//登录
                break;
            case "2":
                prefix = SMSConstant.SMS_REGISTER_KEY_PREFIX;//注册
                break;
            case "3":
                prefix = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX;//更改管理员
                break;
            case "4":
                prefix = SMSConstant.SMS_RESET_KEY_PREFIX;//重置密码
                break;
            default:
                break;
        }
        return prefix;
    }

    /**
     * 验证码校验
     *
     * @param mobile
     * @param type
     * @param checkcode
     * @return
     */
    @Override
    public Boolean verify(String mobile, String type, String checkcode) {

        //校验参数
        if (StrUtil.isEmpty(mobile) || StrUtil.isEmpty(type) || StrUtil.isEmpty(checkcode)) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //组装redis中key
        String key = getPrefix(type) + mobile;

        //获取redis中正确的验证码
        String realCode = redisTemplate.boundValueOps(key).get();

        //验证码对比校验
        if (StrUtil.isNotEmpty(realCode) && realCode.equals(checkcode)) {
            return true;
        }

        return false;
    }
}